//package me.weishu.reflection;
//
//import static android.os.Build.VERSION.SDK_INT;
//
//import android.os.Build;
//import android.util.Log;
//
//import java.lang.reflect.Method;
//
///**
// * @author weishu
// * @date 2020/7/13.
// */
//public final class BootstrapClass {
//
//    private static final String TAG = "BootstrapClass";
//
//    private static Object sVmRuntime;
//    private static Method setHiddenApiExemptions;
//
//    static {
//        if (SDK_INT >= Build.VERSION_CODES.P) {
//            try {
//                Method forName = Class.class.getDeclaredMethod("forName", String.class);
//                Method getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);
//
//                Class<?> vmRuntimeClass = (Class<?>) forName.invoke(null, "dalvik.system.VMRuntime");
//                Method getRuntime = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "getRuntime", null);
//                setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", new Class[]{String[].class});
//                sVmRuntime = getRuntime.invoke(null);
//            } catch (Throwable e) {
//                Log.w(TAG, "reflect bootstrap failed:", e);
//            }
//        }
//    }
//
//    /**
//     * make the method exempted from hidden API check.
//     *
//     * @param method the method signature prefix.
//     * @return true if success.
//     */
//    public static boolean exempt(String method) {
//        return exempt(new String[]{method});
//    }
//
//    /**
//     * make specific methods exempted from hidden API check.
//     *
//     * @param methods the method signature prefix, such as "Ldalvik/system", "Landroid" or even "L"
//     * @return true if success
//     */
//    public static boolean exempt(String... methods) {
//        if (sVmRuntime == null || setHiddenApiExemptions == null) {
//            return false;
//        }
//
//        try {
//            setHiddenApiExemptions.invoke(sVmRuntime, new Object[]{methods});
//            return true;
//        } catch (Throwable e) {
//            return false;
//        }
//    }
//
//    /**
//     * Make all hidden API exempted.
//     *
//     * @return true if success.
//     */
//    public static boolean exemptAll() {
//        return exempt(new String[]{"L"});
//    }
//}
